package com.yikome.purchase.schedule;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.yikome.config.ApiResult;
import com.yikome.purchase.entity.Purchase;
import com.yikome.purchase.entity.PurchaseLogistics;
import com.yikome.purchase.entity.PurchaseProduct;
import com.yikome.purchase.enums.PurchaseStatus;
import com.yikome.purchase.repository.PurchaseLogisticsRepository;
import com.yikome.purchase.repository.PurchaseProductRepository;
import com.yikome.purchase.repository.PurchaseRepository;
import com.yikome.purchase.schedule.dto.BatchReceiptCreateRequest;
import com.yikome.purchase.schedule.dto.BatchReceiptDetailsCreateRequest;
import com.yikome.purchase.schedule.dto.BatchReceiptLogisticsCreateRequest;
import com.yikome.storehouse.entity.Storehouse;
import com.yikome.storehouse.repository.StorehouseRepository;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;

/**
 * 采购单同步至仓库schedule操作
 */
@Component
public class AsyncPurchaseSchedule {
	
	@Autowired
	private PurchaseRepository purchaseRepository ; 
	
	@Autowired
	private PurchaseProductRepository purchaseProductRepository ; 
	
	@Autowired
	private PurchaseLogisticsRepository purchaseLogisticsRepository ; 
	
	@Autowired
	private StorehouseRepository storehouseRepository ; 
	
	@Autowired
	private RestTemplate restTemplate ; 
	
	@Value("${schedule.async.salt}")
	private String salt ; 
	@Value("${schedule.async.purchase.basicUrl}")
	private String basicUrl ; 
	
	/******************************************************************* 新增采购单 **************************************************************************/
	
	@Transactional
	public void asyncPurchaseCreate(Purchase purchase) {
		
		Storehouse storehouse = storehouseRepository.findStorehouse(purchase.getStorehouseId());
		Preconditions.checkArgument(storehouse != null, "仓库不存在");
		Preconditions.checkArgument(StrUtil.isNotBlank(storehouse.getRemoteStorehouseCode()), "远程仓库编码不存在");
		
		List<BatchReceiptCreateRequest> batchReceiptCreateRequests = new ArrayList<>();
		BatchReceiptCreateRequest batchReceiptCreateRequest = new BatchReceiptCreateRequest();
		batchReceiptCreateRequest.setSourceCode(purchase.getPurchaseCode());
		batchReceiptCreateRequest.setComments(purchase.getComments());
		batchReceiptCreateRequest.setStorehouseCode(storehouse.getRemoteStorehouseCode());
		
		List<BatchReceiptDetailsCreateRequest> batchReceiptDetailsCreateRequests = new ArrayList<>();
		List<PurchaseProduct> purchaseProducts = purchaseProductRepository.findPurchaseProduct(purchase.getPurchaseCode());
		for (PurchaseProduct purchaseProduct : purchaseProducts) {
			BatchReceiptDetailsCreateRequest batchReceiptDetailsCreateRequest = new BatchReceiptDetailsCreateRequest();
			batchReceiptDetailsCreateRequest.setName(purchaseProduct.getProductTitle());
			batchReceiptDetailsCreateRequest.setSpecification(purchaseProduct.getProductSkuName());
			batchReceiptDetailsCreateRequest.setBarcode(purchaseProduct.getProductSkuBarcode());
			batchReceiptDetailsCreateRequest.setImage(purchaseProduct.getProductSkuImage());
			batchReceiptDetailsCreateRequest.setPurchasedQuantity(purchaseProduct.getPurchasedQuantity());
			batchReceiptDetailsCreateRequests.add(batchReceiptDetailsCreateRequest);
		}
		batchReceiptCreateRequest.setItems(batchReceiptDetailsCreateRequests);
		
		List<BatchReceiptLogisticsCreateRequest> batchReceiptLogisticsCreateRequests = new ArrayList<>();
		List<PurchaseLogistics> purchaseLogistics = purchaseLogisticsRepository.findPurchaseLogistics(purchase.getPurchaseCode());
		for (PurchaseLogistics purchaseLogistic : purchaseLogistics) {
			BatchReceiptLogisticsCreateRequest batchReceiptLogisticsCreateRequest = new BatchReceiptLogisticsCreateRequest();
			batchReceiptLogisticsCreateRequest.setLogisticCode(purchaseLogistic.getLogisticCode());
			batchReceiptLogisticsCreateRequest.setLogisticComments(purchaseLogistic.getLogisticCompany());
			batchReceiptLogisticsCreateRequests.add(batchReceiptLogisticsCreateRequest);
		}
		batchReceiptCreateRequest.setLogistics(batchReceiptLogisticsCreateRequests);
		
		batchReceiptCreateRequests.add(batchReceiptCreateRequest);
		
		
		HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.add("salt", salt);
        HttpEntity<List<BatchReceiptCreateRequest>> entity = new HttpEntity<>(batchReceiptCreateRequests, headers);
        
		ResponseEntity<ApiResult> exchange = restTemplate.exchange(basicUrl + "create", HttpMethod.POST, entity, ApiResult.class);
		
		Preconditions.checkArgument(HttpStatus.OK == exchange.getStatusCode(), "远程操作不可用...");
        
		if(exchange.getBody().getCode() != ApiResult.CODE_SUCCESS) {
			throw new IllegalArgumentException("远程操作失败.原因: " + exchange.getBody().getMessage());
		}
		
		List<Map<String , Object>> lists = (List<Map<String, Object>>) exchange.getBody().getDatas();
		
		if(!lists.isEmpty()) {
			throw new IllegalArgumentException("远程操作失败.原因: " + lists.get(0).get("errorMsg"));
		}
		
		purchase.setStatus(PurchaseStatus.PURCHASE_ASYNC.getStatus());
		purchaseRepository.save(purchase);
	}

	/******************************************************************* 删除采购单 **************************************************************************/
	
	@Transactional
	public void asyncPurchaseDelete(String purchaseCode) {

		HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.add("salt", salt);
        HttpEntity<List<String>> httpEntity = new HttpEntity<>(ImmutableList.of(purchaseCode), headers);
        
        ResponseEntity<ApiResult> exchange = restTemplate.exchange(basicUrl + "delete", HttpMethod.DELETE, httpEntity, ApiResult.class);
        
        Preconditions.checkArgument(HttpStatus.OK == exchange.getStatusCode(), "远程仓库请求不可用...");
        
        Preconditions.checkArgument((exchange.getBody().getCode() == ApiResult.CODE_SUCCESS), "远程删除失败.原因: " + exchange.getBody().getMessage());
	}
	

	
	/******************************************************************* 采购单新增/修改物流信息 **************************************************************************/
	
	@Transactional
	public void asyncPurchaseLogisticsAdd(String batchNumber , String logisticCode , String logisticCompany) {
		
		HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.add("salt", salt);
        
        BatchReceiptLogisticsCreateRequest logisticsCreateRequest = new BatchReceiptLogisticsCreateRequest();
        logisticsCreateRequest.setReceiptCode(batchNumber);
        logisticsCreateRequest.setLogisticCode(logisticCode);
        logisticsCreateRequest.setLogisticComments(logisticCompany);
        
        HttpEntity<List<BatchReceiptLogisticsCreateRequest>> httpEntity = new HttpEntity<>(ImmutableList.of(logisticsCreateRequest) , headers);
        
        ResponseEntity<ApiResult> exchange = restTemplate.exchange(basicUrl + "logistic", HttpMethod.POST, httpEntity, ApiResult.class);
        
        Preconditions.checkArgument(HttpStatus.OK == exchange.getStatusCode(), "远程仓库请求不可用...");
        
        Preconditions.checkArgument((exchange.getBody().getCode() == ApiResult.CODE_SUCCESS), "远程操作失败.原因: " + exchange.getBody().getMessage());
        
        List<BatchReceiptLogisticsCreateRequest> datas = Convert.toList(BatchReceiptLogisticsCreateRequest.class, exchange.getBody().getDatas());
		
        if(!datas.isEmpty()) throw new RuntimeException("远程操作失败.原因: " + datas.get(0).getErrorMsg());
	}
}
